home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Gold Collection
/
Software Vault - The Gold Collection (American Databankers) (1993).ISO
/
cdr49
/
109_01.zip
/
UCSD2CPM.C
< prev
next >
Wrap
Text File
|
1993-06-26
|
12KB
|
504 lines
/* -------------------------------------------------------
*** Template for Procedure Heading ***
Name:
Result:
Errors:
Globals:
Macros:
Procedures:
Action:
------------------------------------------------------- */
/* : : : : : : : : : : : : : : : : : : : : : : : : : : : :
ucsd2cpm -- Transfer '.TEXT' files from a UCSD directory
formatted disk to a CP/M directory formatted
disk.
1) header blocks removed
2) linefeeds added after carriage returns
3) indents converted to appropriate # of spaces
4) filler nulls removed
5) control-A's removed (added 2/13/80 hrm)
: : : : : : : : : : : : : : : : : : : : : : : : : : : : */
/* : : : : : : : : : : : : : : : : : : : : : : : : : : : :
Constants
: : : : : : : : : : : : : : : : : : : : : : : : : : : : */
#define DLE 0x10 /* Data Link Escape -- indent flag */
#define CR 0x0D /* carriage return */
#define LF 0x0A /* linefeed */
#define NULL 0 /* ascii null */
#define CPM_EOF 0X1A /* CP/M ascii endfile mark */
#define TRUE 1 /* booleans */
#define FALSE 0
#define SEL_DSK 14 /* bdos function number */
#define SET_DMA 26 /* bdos function number */
#define SET_TRK 9 /* bios index number */
#define SET_SEC 10 /* bios index number */
#define READ 12 /* bios index number */
#define DUMMY 0 /* dummy parameter for bios routine */
#define EOF_F 0xFFFF /* end of file flag */
#define D_ENT_SZ 26 /* UCSD directory entry size */
#define D_TITLE 6 /* offset to entry title */
#define UCSD_NAM_SZ 20 /* size of the name part of ucsd dir entry */
#define UCSD_DIR_SZ 2048 /* size of UCSD directory in bytes */
#define SECT_SIZE 128 /* bytes per physical sector */
#define BLOK_SIZE 512 /* bytes per UCSD logical block */
#define SECT_PER_BLOK 4 /* physical sectors per logical block */
/* : : : : : : : : : : : : : : : : : : : : : : : : : : : :
Globals -- these would be static if it were available
: : : : : : : : : : : : : : : : : : : : : : : : : : : : */
int lsn; /* logical sector number */
int lstlsn; /* last logical sector number */
int nbytes; /* number of bytes remaining in ucsd file buffer */
char ucsdbuf[BLOK_SIZE]; /* 1 block buffer for ucsd file */
char *ptr; /* pointer to current byte in ucsd file buffer */
/* : : : : : : : : : : : : : : : : : : : : : : : : : : : :
Global structure type
: : : : : : : : : : : : : : : : : : : : : : : : : : : : */
struct buf {
int fd;
int nleft;
char *nextp;
char buff[SECT_SIZE];
};
/* -------------------------------------------------------
Name: main(argc,argv)
Result: ---
Errors: invocation syntax
Globals: lsn,lstlsn,nbytes,ptr,ucsdbuf
Macros: CPM_FILE,UCSD_FILE,UCSD_NAM_SZ
Procedures: puts(),exit(),force_upr(),printf()
putchar(),close(),unlink(),strcpy()
strcat(),getchar(),open(),copy()
tolower()
Action: Call copy() to copy a '.TEXT' file
from a UCSD formatted disk in drive B
to a user specified file name in
drive A
Handle invocation errors
Handle case of already existing
destination file
------------------------------------------------------- */
#define CPM_FILE argv[1]
#define UCSD_FILE argv[2]
main(argc,argv)
int argc;
char *argv[];
{
int file_id;
char ucsdname[UCSD_NAM_SZ];
lsn = lstlsn = nbytes = 0; /* init globals */
ptr = ucsdbuf;
if( argc != 3 ) {
puts("Proper invocation form is:\n\n");
puts("UCSD2CPM <cpm-file-name> <ucsd-file-name>\n");
puts("This copies B:<ucsd-file-name>.TEXT to A:<cpm-file-name>\n");
exit(1);
}
force_upr(UCSD_FILE); /* make <ucsd-file-name> upper case */
if( (file_id = open(CPM_FILE,0)) >= 0 ) {
printf("%s already exists. Delete it ? ",CPM_FILE);
if( tolower(getchar()) != 'y' ) {
puts("\naborted\n");
exit(1);
}
putchar('\n');
close(file_id);
unlink(CPM_FILE);
}
else
close(file_id);
strcpy(ucsdname,UCSD_FILE);
strcat(ucsdname,".TEXT");
if(copy(ucsdname,CPM_FILE))
printf("\n\nno such file %s .. aborted\n",ucsdname);
exit(0);
}
/* -------------------------------------------------------
Name: copy (ucsd_file,cpm_file)
Result: TRUE if error , FALSE if transfer ok
Errors: no such '.TEXT' file
Globals: struct buf,
Macros: TRUE,EOF_F,CR,DLE,NULL,CPM_EOF,FALSE
Procedures: find_file(),fcreat(),getbyte()
putc(),fflush(),fclose()
Action: Find '.TEXT' file in UCSD directory
on drive B
Create user specified file on
drive A
copy file content from UCSD to CP/M
car by char translating:
Skip header block
Ignore NULL's
Add LF after CR
Convert DLE <count> to
appropriate number of spaces
close output file
------------------------------------------------------- */
copy(ucsd_file,cpm_file)
char *ucsd_file,*cpm_file;
{
struct buf tofile;
int c;
if( ! find_file(ucsd_file) ) /* no such file */
return TRUE;
fcreat(cpm_file,&tofile);
while( (c = getbyte()) != EOF_F )
switch(c) {
case CR: putc(CR,&tofile); /* LF after CR */
putc(LF,&tofile);
break;
case DLE: for( c = (getbyte() - 32); c; c-- )
putc(' ',&tofile); /* fill spaces */
break;
case '\1': /* ignore ^A's */
case NULL: break; /* ignore nulls */
default: putc(c,&tofile); /* pass char unmodified */
break;
}
putc(CPM_EOF,&tofile); /* send cp/m ascii endfile */
fflush(&tofile);
fclose(&tofile);
return FALSE; /* signal transfer ok */
}
/* -------------------------------------------------------
Name: getbyte()
Result: next sequential byte from UCSD '.TEXT' file
Errors:
Globals: lsn,lstlsn,nbytes,ptr,ucsdbuf[]
Macros: EOF_F,BLOK_SIZE,SECT_PER_BLOK
Procedures: read_ucsd()
Action: read block at a time
pass along byte at a time
return EOF_F if end of UCSD file
------------------------------------------------------- */
getbyte()
{
if( lsn > lstlsn)
return EOF_F;
if( nbytes-- )
return *ptr++;
read_ucsd(ucsdbuf,lsn,1);
nbytes = (BLOK_SIZE-1);
ptr = ucsdbuf;
lsn += SECT_PER_BLOK;
return *ptr++;
}
/* -------------------------------------------------------
Name: fclose(file)
Result: status of closing action
Errors: ---
Globals: struct buf
Macros: ---
Procedures: close()
Action: file open for buffered input
or output is closed
------------------------------------------------------- */
fclose(file)
struct buf *file;
{
return close( file->fd );
}
/* -------------------------------------------------------
Name: find_file(ucsd_name)
Result: TRUE if found, FALSE if not found
Errors:
Globals: lsn,lstlsn
Macros: D_ENT_SZ,SECT_PER_BLOK,D_TITLE
TRUE,FALSE,UCSD_DIR_SZ
Procedures: read_ucsd()
Action: ---
------------------------------------------------------- */
find_file(ucsd_name)
char *ucsd_name;
{
char ucsd_dir[UCSD_DIR_SZ];
char *dir,*saved_dir,*name;
int name_len;
name = ucsd_name;
read_ucsd(ucsd_dir,(2*SECT_PER_BLOK),4);
dir = &ucsd_dir[D_TITLE + D_ENT_SZ]; /* skip title block */
while ( dir < &ucsd_dir[UCSD_DIR_SZ] ) {
saved_dir = dir;
if( (name_len = *dir++) <=0 || name_len > 19 )
return FALSE;
while( *dir++ == *name++ ) {
if( --name_len ) /* continue comparison check */
;
else { /* entry found */
dir = saved_dir - D_TITLE; /* point to alloc. info. */
lsn = *dir++;
lsn += *dir++ << 8; /* lsn = starting logical block number */
lsn += 2; /* bypass header blocks */
lsn *= SECT_PER_BLOK; /* 1'st logical sector number */
lstlsn = *dir++;
lstlsn += *dir++ << 8; /* lstlsn = ending logical block # */
lstlsn *= SECT_PER_BLOK; /* lstlsn = last logical sector # */
return TRUE; /* indicate file found */
}
}
name = ucsd_name; /* reset comparison name pointer */
dir = saved_dir + D_ENT_SZ; /* point at next entry name */
}
return FALSE; /* no such file */
}
/* -------------------------------------------------------
Name: read_ucsd()
Result: status of selecting drive A
Errors: sector read error
Globals: ---
Macros: SEL_DSK,SET_DMA,SET_TRK,SET_SEC
READ,DUMMY,SECT_SIZE
Procedures: bios(),bdos(),printf(),exit()
Action: Read count blocks from drive B
into buf starting at UCSD logical
record number rn
------------------------------------------------------- */
read_ucsd(buf,rn,count)
char *buf;
unsigned rn;
int count;
{
char bios();
int seccnt; seccnt = count*4;
bdos(SEL_DSK,1);
while( seccnt-- ) {
bdos(SET_DMA,buf);
bios(SET_TRK,track(rn));
bios(SET_SEC,sector(rn));
if( bios(READ,DUMMY) ) {
printf("read error @ track %2d sector %2d",track(rn),sector(rn));
exit(1);
}
buf += SECT_SIZE;
rn++;
}
return bdos(SEL_DSK,0);
}
/* -------------------------------------------------------
Name: sector(rn)
Result: absolute sector number
Errors: ---
Globals: ---
Macros: ---
Procedures: ---
Action: convert logical record number
to absolute sector
maps logical records to physical sectors
by selecting every second sector in order
(accounting for the modulo 26 process)
on the diskette except that at a track
switchover point there is an additional
'gap' of 6 sectors (total of 7) to allow
for the drive to seek. This is UCSD's
attempt to minimize disk access time.
------------------------------------------------------- */
sector(rn)
unsigned rn;
{
unsigned t1,t2,trk,t3,sect;
t1 = rn % 26;
t2 = t1 << 1;
if(t1 > 12)
t2++;
trk = rn/26; /* zero based absolute track */
t3 = t2 + 6*trk; /* new logical sector number */
sect = t3 % 26; /* new zero based absolute sector */
return ++sect; /* one based absolute sector */
}
/* -------------------------------------------------------
Name: track(rn)
Result: absolute track number
Errors: ---
Globals: ---
Macros: ---
Procedures: ---
Action: convert logical sector number to
absolute track This is simply the modulo
26 process except that track 0 is not
considered part of the logical
sector space.
------------------------------------------------------- */
track(rn)
unsigned rn;
{
return rn/26 + 1;
}
/* -------------------------------------------------------
Name: index(str,sstr)
Result: position of string sstr in string str
-1 if not a substring
Errors: ---
Globals: ---
Macros: ---
Procedures: ---
Action: ---
------------------------------------------------------- */
index(str,sstr)
char *str,*sstr;
{
int first_match;
if( *sstr == 0 ) /* null string is a substring of all strings */
return 0;
for( first_match=0; *str != *sstr; first_match++)
if( *str == 0 )
return -1;
else
str++;
while( *sstr )
if( *str++ != *sstr++ )
return -1;
return first_match;
}
/* -------------------------------------------------------
Name: force_upr(string)
Result: ---
Errors: ---
Globals: ---
Macros: ---
Procedures: ---
Action: force each char of string to upper case
------------------------------------------------------- */
force_upr(string)
char *string;
{
while(*string)
*string = *string++;
return;
}
/* -------------------------------------------------------
Name: print(string,n)
Result: ---
Errors: ---
Globals: ---
Macros: ---
Procedures: putchar()
Action: print n chars to console starting
at char pointer string
------------------------------------------------------- */
print(string,n)
char *string;
int n;
{
while(n--)
putchar(*string++);
return;
}